<?php

abstract class Request {
	
	private static
		$_params = null;
	
	/**
	 * 获取 url
	 * @return 当前 url
	 */
	public function url() {
		return self::protocol() . self::host() . self::uri();
	}
	
	/**
	 * 获取 http | https + ://
	 * @return http | https + ://
	 */
	public function protocol() {
		return strtolower(substr($_SERVER['SERVER_PROTOCOL'], 0, strpos($_SERVER['SERVER_PROTOCOL'], '/'))) . '://';
	}
	
	/**
	 * 获取 host
	 * @return 当前 host
	 */
	public function host() {
		return $_SERVER['HTTP_HOST'];
	}
	
	/**
	 * 获取 uri
	 * @return 当前 uri
	 */
	public function uri() {
		return isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : (isset($_SERVER['argv']) ? $_SERVER['PHP_SELF'].'?'.$_SERVER['argv'][0] : $_SERVER['PHP_SELF'] .'?'. $_SERVER['QUERY_STRING']);
	}

	/**
	 * 获取 method，get | post | put
	 * @return get | post | put
	 */
	public function method() {
		return strtolower($_SERVER['REQUEST_METHOD']);
	}

	public function format() {
		return Response::get('format');
	}
	
	/**
	 * 判断当前请求是不是 post
	 * @return true | false
	 */
	public function isPost() {
		return self::method() == 'post';
	}

	/**
	 * 判断当前请求是不是 ajax 请求
	 * @return true false
	 */
	public function isAjax() {
		
	}

	/**
	 * 获取 get 和 post 的值
	 * @params string|array
	 * @params boolean $is_cookie
	 */
	public function params($m_key = null, $is_cookie = false) {
		if (is_array($m_key)) {
			$k_result = array();
			foreach ($m_key as $s_name)
				$k_result[$s_name] = Request::params($s_name, $is_cookie);
			unset($m_key);
			return $k_result;
		}
		else {
			if (!$is_cookie && self::$_params === null)
				self::$_params = array_merge($_GET, $_POST); // 将params 进行缓存, POST将覆盖GET的值
			if ($m_key === null)
				return $is_cookie 
				   ? array_map(array('Request', 'strFilter'), $_COOKIE) 
				   : array_map(array('Request', 'strFilter'), self::$_params);
			if ($is_cookie)
				return isset($_COOKIE[$m_key]) ? Request::strFilter($_COOKIE[$m_key]) : null;
			else
				return isset(self::$_params[$m_key]) ? Request::strFilter(self::$_params[$m_key]) : null;
		}
	}
	
	public function cookies($m_key = null) {
		return Request::params($m_key, true);
	}
	
	protected static function strFilter($s_val) {
		return addslashes($s_val);
	}
}

class Route extends AbsRouteSettings {

	public static function mapping() {
		$s_uri = self::uriFilter(Request::uri());
		$a_match = array();
		foreach (self::$rules as $a_val) {
			if (!isset($a_val['rule'])) continue;
			$m_rule = array_shift($a_val); // 取出rule
			if (is_array($m_rule)) {
				$s_rule = array_shift($m_rule);
				$a_rule_keys =  array_keys($m_rule);
				$s_rule = str_replace($a_rule_keys, array_values($m_rule), $s_rule);
			}
			else $s_rule = $m_rule;
			$s_rule = '/^'.$s_rule.'$/i';
			if (preg_match($s_rule, $s_uri, $a_match) == true) {
				if (isset($a_val['build'])) unset($a_val['build']);
				if (isset($a_rule_keys)) {
					$i_idx = 0;
					foreach ($a_rule_keys as $s_var_name) {
						++$i_idx;
						$s_var_name = substr($s_var_name, 1);
						$a_val[$s_var_name] = isset($a_match[$i_idx]) ? $a_match[$i_idx] : null;
					}
				}
				if (!isset($a_val['action'])) $a_val['action'] = self::$def_action;
				if (!isset($a_val['format']) || empty($a_val['format'])) $a_val['format'] = self::$def_format;
				if (!isset($a_val['controller'])) $a_val['controller'] = self::$def_controller;
				return $a_val;
			}
		}
		return Response::halt('no_route');
	}
	
	public static function uriFilter($s_uri, $k_replace = null) {
		$k_filter_base = array('/\/+/i' => '/', '/^\/+/i'	=> '', '/\/+$/i' => '');
		$k_replace = (!is_null($k_replace) && is_array($k_replace)) 
			? array_merge($k_filter_base, $k_replace) 
			: $k_filter_base;
		$s_uri = preg_replace(array_keys($k_replace), array_values($k_replace), $s_uri);
		return $s_uri;
	}
}

abstract class Response {
	
	private static
		$_status = -1,
		$_settings = array(),
		$_instance;
		
	public function instance() {
		if (self::$_status === -1) {
			self::set(Route::mapping());
			self::init();
		}
	}

	private function init() {
		$s_ctl = String::camelize(self::get('controller'));
		$s_ctl_file = AGI_APP_C . '/' . $s_ctl . '.php';
		if (!file_exists($s_ctl_file)) self::halt('no_ctl_file');
		else {
			require $s_ctl_file;
		}
		$s_ctl_cls = $s_ctl . 'Controller';
		$s_act_mtd = String::camelize(self::get('action')) . 'Action';
		if (class_exists($s_ctl_cls)) self::$_instance = new $s_ctl_cls();
		else self::halt('no_ctl');
		if (method_exists(self::$_instance, $s_act_mtd)) self::$_instance->$s_act_mtd();
		else self::halt('no_act');
		// 完成Response类初始化准备
		self::$_status = 0;
	}
	
	public function halt($s_msg) {
		exit($s_msg);
	}
	
	public function runtime() {
		
	}
	
	public function memory($is_real = false) {
		return memory_get_usage($is_real) . ' / ' . memory_get_peak_usage($is_real);
	}
	
	public function set($m_key, $m_val = false) {
		if (is_array($m_key)) {
			self::$_settings = array_merge(self::$_settings, $m_key);
			return $m_key;
		}
		else {
			self::$_settings[$m_key] = $m_val;
			return $m_val;
		}
	}
	
	public function get($m_key = null) {
		if ($m_key === null) return self::$_settings;
		if (is_array($m_key)) {
			$k_result = array();
			foreach ($m_key as $s_name)
				$k_result[$s_name] = isset(self::$_settings[$s_name]) ? self::$_settings[$s_name] : false;
		}
		else {
			$k_result = isset(self::$_settings[$m_key]) ? self::$_settings[$m_key] : null;
		}
		return $k_result;
	}
}

abstract class AbsController {
	
	public static $layout = false;
	
	protected
		$_vars = array(),
		$_model_register = array();
	
	public function __construct() {
		
	}
	
	public function using($s_model) {
		if (in_array($this->_model_register, $s_model)) Response::halt('mod_using');
		$s_model_file = AGI_APP_M . '/' . $s_model . 'php';
		if (!file_exists($s_model_file)) Response::halt('no_mod_file');
		else {
			include $s_model_file;
			$this->_model_register[] = $s_model;
		}
	}
	
	public function bind($m_key, $m_val = null) {
		if (is_array($m_key)) {
			$this->_vars = array_merge($this->_vars, $m_key);
			return $m_key;
		}
		else {
			$this->_vars[$m_key] = $m_val;
			return $m_val;
		}
	}
	
	public function query($m_key = null) {
		if ($m_key === null) return $this->_vars;
		if (is_array($m_key)) {
			$k_result = array();
			foreach ($m_key as $s_name)
				$k_result[$m_key] = isset($this->_vars[$s_name]) ? $this->_vars[$s_name] : null;
		}
		else {
			$k_result = isset($this->_vars[$m_key]) ? $this->_vars[$m_key] : null;
		}
		return $k_result;
	}
	
	public function layout($s_val = false) {
		self::$layout = $s_val;
	}
}

/**
 * 以下扩展为有针对性的扩展，并以类的形式作为命名空间
 */
class String {
	
	/**
	 * 首字母大写
	 */
	public function capitalize($s_val = null) {
		if ($s_val === null) return null;
		$s_val{0} = strtoupper($s_val{0});
		return $s_val;
	}
	
	/**
	 * 驼峰命名生成
	 * @param $s_val 输入值
	 * @param $s_split 分割标识符
	 * @return string 
	 */
	public function camelize($s_val = null, $s_split = '_') {
		if ($s_val === null) return null;
		$s_val = preg_replace('/'.$s_split.'([a-z]{1})?/e', 'strtoupper(\'\\1\')', $s_val);
		return $s_val;
	}
	
	/**
	 * 驼峰还原
	 */
	public function unCamelize($s_val = null, $s_split = '_') {
		if ($s_val === null || $s_split === null) return null;
		$s_val = preg_replace('/([A-Z]{1})/e', '$s_split . strtolower(\'\\1\')', $s_val);
		return $s_val;
	}
}

class File {
	public function load($s_file, $s_mode = 'rb') {
		
	}
}

/**
 * 以下定义函数为某些类的快捷方式
 * Janpoem 2008.8.2
 */

function params($m_key = null) {
	return Request::params($m_key, false);
}

function cookies($m_key = null) {
	return Request::params($m_key, true);
}
?>